package com.jd.scaffold.common.utils;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 描述: 系统通用金额计算工具类
 * <p>创建人：jrzhangwei 创建日期：2014年5月12日 </p>
 * 
 * @version V1.0
 */
public class CurrencyUtils{

	@SuppressWarnings("unused")
	private final static Logger log = LoggerFactory.getLogger(CurrencyUtils.class);

	private final static int DEFAULT_AMT_DIGTIAL_COUNT = 2;
	
	private final static int DEFAULT_AMT_COMPARE_DIGTIAL_COUNT = 11; 
	/**
	 * 描述: 获取最小值
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:30:43</p>
	 * 
	 * @param amt0
	 * @param amt1
	 * @return
	 */
	public static BigDecimal min(BigDecimal amt0, BigDecimal amt1) {
		if (isAmtGreat(amt0, amt1)) {
			return amt1;
		}// 小于等于
		return amt0;
	}

    /**
     * 描述: 获取最小值
     * <p>创建人：jrzhangwei , 2014年5月12日 下午2:30:43</p>
     *
     * @param amt0
     * @param amt1
     * @return
     */
    public static BigDecimal max(BigDecimal amt0, BigDecimal amt1) {
        if (isAmtGreat(amt0, amt1)) {
            return amt0;
        }
        return amt1;
    }

	/**
	 * 描述: 字符串转化为BigDecimal类型
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:30:43</p>
	 * @param amt0 需要转换的数值
	 * @return
	 */
	public static BigDecimal getBigDecimal(String amt0) {
		if(amt0==null || "".equals(amt0.trim())){
			return BigDecimal.ZERO;
		}
		amt0 = amt0.trim();
		BigDecimal amt = new BigDecimal(amt0);
		return getZeroBigDecimalIfNull(amt);
	}

	/**
	 * 描述: 数据直接修约
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:33:13</p>
	 * 
	 * @param amt
	 *            需修约的数字
	 * @param reservedDigCount
	 *            保留精度
	 * @param roundingMode
	 *            修约方式
	 * @return
	 */
	public static BigDecimal roundingResult(BigDecimal amt, int reservedDigCount, RoundingMode roundingMode) {
		amt = getZeroBigDecimalIfNull(amt);
		amt = amt.setScale(reservedDigCount, roundingMode);
		return amt;
	}

	/**
	 * 描述: 数据直接修约
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:33:13</p>
	 * 
	 * @param amt
	 *            需修约的数字
	 * @return
	 */
	public static BigDecimal getBigDecimalWhenEvenUp(BigDecimal amt) {
		amt = roundingResult(amt, CurrencyUtils.DEFAULT_AMT_DIGTIAL_COUNT,RoundingMode.HALF_UP);
		return amt;
	}

	/**
	 * 描述: 第一个数是比较第二个数 如果左边>右边则返回>0 如果相等 返回0 如果左边<右边返回负数
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:15:16</p>
	 * 
	 * @param amt0
	 * @param amt1
	 * @return
	 */
	public static int amtCompare(BigDecimal amt0, BigDecimal amt1) {
		amt0 = getZeroBigDecimalIfNull(amt0);
		amt1 = getZeroBigDecimalIfNull(amt1);
		return amt0.compareTo(amt1);
	}

	/**
	 * 描述: 判断第一个数是否等于第二个数
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:09:19</p>
	 * 
	 * @param amt0
	 *            第一个数
	 * @param amt1
	 *            第二个数
	 * @return
	 */
	public static boolean isAmtEqual(BigDecimal amt0, BigDecimal amt1) {
		if (amtCompare(amt0, amt1) == 0) {
			return true;
		}
		return false;
	}

	/**
	 * 描述: 判断第一个数是否大于第二个数
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:09:19</p>
	 * 
	 * @param amt0
	 *            第一个数
	 * @param amt1
	 *            第二个数
	 * @return
	 */
	public static boolean isAmtGreat(BigDecimal amt0, BigDecimal amt1) {
		if (amtCompare(amt0, amt1) > 0) {
			return true;
		}
		return false;
	}

	/**
	 * 描述: 判断第一个数是否大于等于第二个数
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:09:19</p>
	 * 
	 * @param amt0
	 *            第一个数
	 * @param amt1
	 *            第二个数
	 * @return
	 */
	public static boolean isAmtGreatAndEqual(BigDecimal amt0, BigDecimal amt1) {
		if (amtCompare(amt0, amt1) >= 0) {
			return true;
		}
		return false;
	}

	/**
	 * 描述: 判断金额是否大于0
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:05:10</p>
	 * 
	 * @param amt0
	 *            需要判断的金额
	 * @return
	 */
	public static boolean isAmtGreatThanZero(BigDecimal amt0) {
		if (amtCompare(amt0, BigDecimal.ZERO) > 0) {
			return true;
		}
		return false;
	}
	
	/**
	 * 描述: 判断金额是否大于等于0
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:05:10</p>
	 * 
	 * @param amt0
	 *            需要判断的金额
	 * @return
	 */
	public static boolean isAmtGreatThanOrEqualZero(BigDecimal amt0) {
		if (amtCompare(amt0, BigDecimal.ZERO) >= 0) {
			return true;
		}
		return false;
	}


	/**
	 * 描述: 判断金额是否小于0
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:03:04</p>
	 * 
	 * @param amt0
	 *            需要判断的金额
	 * @return
	 */
	public static boolean isAmtLessThanZero(BigDecimal amt0) {
		if (amtCompare(amt0, BigDecimal.ZERO) < 0) {
			return true;
		}
		return false;
	}

	/**
	 * 描述:判断金额是否小于等于0
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:02:01</p>
	 * 
	 * @param amt0
	 *            需要判断的金额
	 * @return
	 */
	public static boolean isAmtLessThanOrEqualZero(BigDecimal amt0) {
		if (amtCompare(amt0, BigDecimal.ZERO) <= 0) {
			return true;
		}
		return false;
	}

	/**
	 * 描述: 判断金额是否等于0
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午1:46:15</p>
	 * 
	 * @param amt0
	 *            需要判断的金额
	 * @return
	 */
	public static boolean isAmtEqualZero(BigDecimal amt0) {
		if (amtCompare(amt0, BigDecimal.ZERO) == 0) {
			return true;
		}
		return false;
	}

	/**
	 * 描述: 格式化浮点数
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午1:45:26</p>
	 * 
	 * @param digital
	 *            需要格式化的数字
	 * @param count
	 *            保留精度
	 * @return
	 */
	public static String formatDigital(double digital, int count) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < count; i++) {
			sb.append("0");
		}
		NumberFormat format = new DecimalFormat("#0." + sb.toString());
		return format.format(digital);
	}

	/**
	 * 描述: 如果input为空返回零
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午1:44:53</p>
	 * 
	 * @param input
	 *            判断值
	 * @return
	 */
	public static BigDecimal getZeroBigDecimalIfNull(BigDecimal input) {
		return input == null ? BigDecimal.ZERO : input;
	}
	
	/**
	 * 
	 * 描述: 计算两个金额相加
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午3:07:55</p>
	 * @param amt0 第一个金额
	 * @param amt1 第二个金额
	 * @return
	 */
	public static BigDecimal amtAdd(BigDecimal amt0, BigDecimal amt1) {
		amt0 = getZeroBigDecimalIfNull(amt0);
		amt1 = getZeroBigDecimalIfNull(amt1);
		return getBigDecimalWhenEvenUp(amt0.add(amt1));
	}
	
	/**
	 * 
	 * 描述: 计算两个金额相减
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午3:07:55</p>
	 * @param amt0 第一个金额（被减数）
	 * @param amt1 第二个金额（减数）
	 * @return
	 */
	public static BigDecimal amtSubs(BigDecimal amt0, BigDecimal amt1) {
		amt0 = getZeroBigDecimalIfNull(amt0);
		amt1 = getZeroBigDecimalIfNull(amt1);
		return getBigDecimalWhenEvenUp(amt0.subtract(amt1));
	}
	
	/**
	 * 
	 * 描述: 计算两个金额相乘
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午3:07:55</p>
	 * @param amt0 第一个金额
	 * @param amt1 第二个金额
	 * @return
	 */
	public static BigDecimal amtMult(BigDecimal amt0, BigDecimal amt1) {
		return amtMult(amt0, amt1,2, RoundingMode.HALF_UP);
	}
	
	/**
	 * 
	 * 描述: 计算两个金额相乘
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午3:07:55</p>
	 * @param amt0 第一个金额
	 * @param amt1 第二个金额
	 * @param reservedDigCount 数据保留精度
	 * @param roundingMode 数据舍入方式
	 * @return
	 */
	public static BigDecimal amtMult(BigDecimal amt0, BigDecimal amt1,int reservedDigCount, RoundingMode roundingMode) {
		amt0 = getZeroBigDecimalIfNull(amt0);
		amt1 = getZeroBigDecimalIfNull(amt1);
		return  roundingResult(amt0.multiply(amt1,MathContext.DECIMAL32),reservedDigCount,roundingMode);
	}
	
	/**
	 * 
	 * 描述: 计算两个金额相除
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午3:07:55</p>
	 * @param amt0 第一个金额（被除数）
	 * @param amt1 第二个金额（除数）
	 * @return
	 */
	public static BigDecimal amtDiv(BigDecimal amt0, BigDecimal amt1) {
		return amtDiv(amt0,amt1,CurrencyUtils.DEFAULT_AMT_COMPARE_DIGTIAL_COUNT,RoundingMode.HALF_UP);
	}
	
	/**
	 * 
	 * 描述: 计算两个金额相除
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午3:07:55</p>
	 * @param amt0 第一个金额（被除数）
	 * @param amt1 第二个金额（除数）
	 * @param reservedDigCount 数据保留精度
	 * @param roundingMode 数据舍入方式
	 * @return
	 */
	public static BigDecimal amtDiv(BigDecimal amt0, BigDecimal amt1,int reservedDigCount, RoundingMode roundingMode) {
		amt0 = getZeroBigDecimalIfNull(amt0);
		amt1 = getZeroBigDecimalIfNull(amt1);
		if(isAmtEqualZero(amt1)){
			throw new RuntimeException("除数为空！");
		}
		return amt0.divide(amt1,reservedDigCount,roundingMode);
	}
	
	/**
	 * 描述: 数据直接修约
	 * <p>创建人：jrzhangwei , 2014年5月12日 下午2:33:13</p>
	 * @param amt 需修约的数字
	 * @param roundingMode 修约方法
	 * @return
	 */
	public static BigDecimal getBigDecimalWhenEvenUp(BigDecimal amt,RoundingMode roundingMode) {
		amt = roundingResult(amt,CurrencyUtils.DEFAULT_AMT_DIGTIAL_COUNT,roundingMode);
		return amt;
	}
	
	/**
	 * 
	 * 描述:去除空格
	 * <p>创建人：jrzhangwei , 2014年12月10日 上午8:28:31</p>
	 * @param str 需要去除空格的字符串
	 * @return
	 */
	public static String trimToEmpty(String str) {
        return str == null ? "" : str.trim();
    }
}
